package v1alpha1

import (
	appv1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// MariaDBClusterList a set of mariadb cluster
type MariaDBClusterList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata"`
	Items           []MariaDBCluster `json:"items"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// MariaDBCluster mariadb cluster
type MariaDBCluster struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata"`
	Spec              MariaDBClusterSpec   `json:"spec"`
	Status            MariaDBClusterStatus `json:"status,omitempty"`
}

// MariaDBClusterSpec define mariadb cluster spec
type MariaDBClusterSpec struct {
	Replicas         int32                       `json:"replicas,omitempty"`
	Image            string                      `json:"image,omitempty"`
	StorageSize      string                      `json:"storageSize,omitempty"`
	StorageClass     string                      `json:"storageClass,omitempty"`
	CMName           string                      `json:"configMap,omitempty"`
	RestartPolicy    string                      `json:"restartPolicy,omitempty"`
	Resources        corev1.ResourceRequirements `json:"resources,omitempty"`
	DatabaseName     string                      `json:"databaseName,omitempty"`
	DatabaseUser     string                      `json:"databaseUser,omitempty"`
	DatabasePassword string                      `json:"databasePassword,omitempty"`
	DataFrom         string                      `json:"dataFrom,omitempty"`
	Monitor          bool                        `json:"monitor"`
}

// MariaDBClusterStatus mariadb cluster status
type MariaDBClusterStatus struct {
	appv1.StatefulSetStatus `json:",inline"`
}

// S3StorageProvider represents an S3 compatible bucket for storing Backups.
type S3StorageProvider struct {
	// Region in which the S3 compatible bucket is located.
	Region string `json:"region"`
	// Endpoint (hostname only or fully qualified URI) of S3 compatible
	// storage service.
	Endpoint string `json:"endpoint"`
	// Bucket in which to store the Backup.
	Bucket string `json:"bucket"`
	// ForcePathStyle when set to true forces the request to use path-style
	// addressing, i.e., `http://s3.amazonaws.com/BUCKET/KEY`. By default,
	// the S3 client will use virtual hosted bucket addressing when possible
	// (`http://BUCKET.s3.amazonaws.com/KEY`).
	ForcePathStyle bool `json:"forcePathStyle"`
	// CredentialsSecret is a reference to the Secret containing the
	// credentials authenticating with the S3 compatible storage service.
	CredentialsSecret *corev1.LocalObjectReference `json:"credentialsSecret"`
}

// QiniuStorageProvider represents an qiniu compatible bucket for storing Backups.
type QiniuStorageProvider struct {
	AccessKey string `json:"accessKey"`
	SecretKey string `json:"secretKey"`
	Bucket    string `json:"bucket"`
	IO        string `json:"io"`
	API       string `json:"api"`
	UP        string `json:"up"`
}

// StorageProvider defines the configuration for storing a Backup in a storage
// service.
type StorageProvider struct {
	S3 *S3StorageProvider `json:"s3"`
	// TODO expensions another storage
	Qiniu *QiniuStorageProvider
}

// BackupCMD backup mariadb data cmd expression, cmd include xtrabackup、mysqldump, databases represent the databases to backup.
// it's like: mysql,test,demo. it's means will backup three database data. if vaule is "*", that's means backup all databases.
type BackupCMD struct {
	CMD       string `json:"cmd"`
	Databases string `json:"databases"`
}

// BackupSpec defines the specification for a Maria backup. This includes what should be backed up,
// what tool should perform the backup, and, where the backup should be stored.
type BackupSpec struct {
	// Executor is the configuration of the tool that will produce the backup, and a definition of
	// what databases and tables to backup.
	Executor BackupCMD `json:"executor"`
	// StorageProvider configures where and how backups should be stored.
	StorageProvider StorageProvider `json:"storageProvider"`
	// Clusters is the Cluster list to backup.
	Cluster string `json:"cluster"`
}

// BackupConditionType represents a valid condition of a Backup.
type BackupConditionType string

const (
	// BackupRunning means the Backup is currently being executed by a
	// Cluster member's mysql-agent side-car.
	BackupRunning BackupConditionType = "Running"
	// BackupComplete means the Backup has successfully executed and the
	// resulting artifact has been stored in object storage.
	BackupComplete BackupConditionType = "Complete"
	// BackupFailed means the Backup has failed.
	BackupFailed BackupConditionType = "Failed"
)

// BackupCondition describes the observed state of a Backup at a certain point.
type BackupCondition struct {
	Type   BackupConditionType
	Status corev1.ConditionStatus
	// +optional
	LastTransitionTime metav1.Time
	// +optional
	Reason string
	// +optional
	Message string
}

// BackupOutcome describes the location of a Backup
type BackupOutcome struct {
	// Location is the Object Storage network location of the Backup.
	Location string `json:"location"`
}

// BackupStatus captures the current status of a Backup.
type BackupStatus struct {
	// Counts represent the backup count of mariadb cluster
	Counts int32 `json:"counts,omitempty"`
	// Outcome holds the results of a successful backup.
	// +optional
	Outcome BackupOutcome `json:"outcome,omitempty"`
	// TimeStarted is the time at which the backup was started.
	// +optional
	TimeStarted metav1.Time `json:"timeStarted,omitempty"`
	// TimeCompleted is the time at which the backup completed.
	// +optional
	TimeCompleted metav1.Time `json:"timeCompleted,omitempty"`
	// +optional
	Conditions []BackupCondition `json:"conditions,omitempty"`
}

// +genclient
// +genclient:noStatus
// +resourceName=mysqlbackups
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// MariaDBBackup is a backup of a Cluster.
type MariaDBBackup struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata"`

	Spec   BackupSpec   `json:"spec"`
	Status BackupStatus `json:"status,omitempty"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// MariaDBBackupList is a list of Backups.
type MariaDBBackupList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata"`

	Items []MariaDBBackup `json:"items"`
}

// CronBackupSpec defines the specification for a MySQL backup schedule.
type CronBackupSpec struct {
	// Schedule specifies the cron string used for backup scheduling.
	Schedule string `json:"schedule"`

	// BackupTemplate is the specification of the backup structure
	// to get scheduled.
	BackupTemplate BackupSpec `json:"backupTemplate"`
}

// CronStatus captures the current state of a MySQL backup cronjob.
type CronStatus struct {
	// LastBackup is the last time a Backup was run for this
	// backup schedule.
	// +optional
	Counts     int         `json:"counts"`
	LastBackup metav1.Time `json:"lastBackup"`
	Conditions []BackupCondition
}

// MariaDBCronBackup is a backup cron for a Cluster.
type MariaDBCronBackup struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata"`

	Spec   CronBackupSpec `json:"spec"`
	Status CronStatus     `json:"status,omitempty"`
}

// MariaDBCronBackupList is a list of CronBackup.
type MariaDBCronBackupList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata"`

	Items []MariaDBCronBackup `json:"items"`
}

// BackupTask backup task will send to rabbitmq
type BackupTask struct {
	BackupName      string `json:"backupName"`
	BackupNamespace string `json:"backupNamespace"`
	Command         string `json:"command"`
	ClusterName     string `json:"clusterName"`
	Type            string `json:"type"` // backup cronBackup
}

// Restore mariadb restore
type Restore struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata"`
	Spec              RestoreSpec   `json:"spec"`
	Status            RestoreStatus `json:"status,omitempty"`
}

// RestoreSpec mariadb restore spec
type RestoreSpec struct {
	DataFrom         string `json:"dataFrom,omitempty"`
	ClusterReference string `json:"clusterReference,omitempty"`
}

// RestoreStatus restore status
type RestoreStatus struct {
	TimeStarted metav1.Time `json:"timeStarted,omitempty"`
	// TimeCompleted is the time at which the backup completed.
	// +optional
	TimeCompleted metav1.Time `json:"timeCompleted,omitempty"`
	// +optional
	Conditions []RestoreCondition `json:"conditions,omitempty"`
}

// RestoreCondition describes the observed state of a restore at a certain point.
type RestoreCondition struct {
	Type   RestoreConditionType
	Status corev1.ConditionStatus
	// +optional
	LastTransitionTime metav1.Time
	// +optional
	Reason string
	// +optional
	Message string
}

// RestoreList restore list
type RestoreList struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata"`
	Items             []Restore `json:"items"`
}

// RestoreConditionType represents a valid condition of a Restore.
type RestoreConditionType string

const (
	// RestoreRunning means the Restore is currently being executed by a
	// Cluster member's mysql-agent side-car.
	RestoreRunning RestoreConditionType = "Running"
	// RestoreComplete means the Restore has successfully executed and the
	// resulting artifact has been stored in object storage.
	RestoreComplete RestoreConditionType = "Complete"
	// RestoreFailed means the Restore has failed.
	RestoreFailed RestoreConditionType = "Failed"
)

// RestoreTask restore task will send to rabbitmq
type RestoreTask struct {
	RestoreName      string `json:"backupName"`
	RestoreNamespace string `json:"backupNamespace"`
	Command          string `json:"command"`
	ClusterName      string `json:"clusterName"`
	FileName         string `json:"fileName,omitempty"`
}
